package cn.uin.infrastructure.adapter.repository;

import cn.uin.domain.auth.adapter.repository.IAuthRepository;
import cn.uin.domain.auth.model.aggregate.UserInfoAggregate;
import cn.uin.domain.auth.model.entity.*;
import cn.uin.infrastructure.dao.*;
import cn.uin.infrastructure.dao.po.*;
import cn.uin.infrastructure.redis.IRedisService;
import cn.uin.types.common.RedisConstants;
import cn.uin.types.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther: uIn
 * @Date: 2025/10/19 - 10 - 19 - 18:38
 * @Description: cn.uin.infrastructure.adapter.repository
 * @version: 1.0
 */
@Slf4j
@Repository
public class AuthRepository implements IAuthRepository {

    @Resource
    private HomeMenuDao homeMenuDao;

    @Resource
    private HomeRoleDao homeRoleDao;

    @Resource
    private HomeUserDao homeUserDao;

    @Resource
    private IRedisService redisService;

    @Resource
    private HomeLoginLogDao homeLoginLogDao;

    @Resource
    private HomeUserDetailDao homeUserDetailDao;


    @Override
    public HomeUserEntity queryUserByUserName(String username) {
        HomeUser homeUser = homeUserDao.queryUserByUserName(username);
        if (ObjectUtils.isEmpty(homeUser)) return null;
        return HomeUserEntity.builder()
                .id(homeUser.getId())
                .username(homeUser.getUsername())
                .password(homeUser.getPassword())
                .email(homeUser.getEmail())
                .phone(homeUser.getPhone())
                .status(homeUser.getStatus())
                .build();
    }

    @Override
    public HomeUserEntity queryUserByUserPhone(String phone) {
        HomeUser homeUser = homeUserDao.queryUserByUserPhone(phone);
        if (ObjectUtils.isEmpty(homeUser)) return null;
        return HomeUserEntity.builder()
                .id(homeUser.getId())
                .username(homeUser.getUsername())
                .password(homeUser.getPassword())
                .email(homeUser.getEmail())
                .phone(homeUser.getPhone())
                .status(homeUser.getStatus())
                .build();
    }

    @Override
    public HomeUserEntity queryUserByUserEmail(String email) {
        HomeUser homeUser = homeUserDao.queryUserByEmail(email);
        if (ObjectUtils.isEmpty(homeUser)) return null;
        return HomeUserEntity.builder()
                .id(homeUser.getId())
                .username(homeUser.getUsername())
                .password(homeUser.getPassword())
                .email(homeUser.getEmail())
                .phone(homeUser.getPhone())
                .status(homeUser.getStatus())
                .build();
    }

    @Override
    public void saveUser(HomeUserRegisterEntity homeUserRegisterEntity) {
        HomeUser user = HomeUser.builder()
                .username(homeUserRegisterEntity.getUsername())
                .password(homeUserRegisterEntity.getPassword())
                .email(homeUserRegisterEntity.getEmail())
                .phone(homeUserRegisterEntity.getPhone())
                .registerType(homeUserRegisterEntity.getType())
                .build();
        homeUserDao.insert(user);
    }

    @Override
    public List<HomeRoleEntity> queryRolesByUserName(String username) {
        List<HomeRole> homeRoles = homeRoleDao.queryRolesByUserName(username);
	    return homeRoles.stream().map(item -> {
            HomeRoleEntity homeRoleEntity = new HomeRoleEntity();
            homeRoleEntity.setRoleName(item.getRoleName());
            homeRoleEntity.setRoleCode(item.getRoleCode());
            homeRoleEntity.setDesc(item.getDesc());
            homeRoleEntity.setId(item.getId());
            return homeRoleEntity;
        }).collect(Collectors.toList());
    }

    @Override
    public List<HomeMenuEntity> queryMenusByUserName(String username) {
        List<HomeRoleEntity> homeRoles = queryRolesByUserName(username);
        List<HomeMenuEntity> homeMenuList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(homeRoles)) {
            // 获取角色对应的菜单
            homeRoles.forEach(item -> {
                List<HomeMenuEntity> homeMenus = queryMenusByRoleId(item.getId());
                homeMenuList.addAll(homeMenus);
            });
        }
        // 菜单去重
        List<HomeMenuEntity> menus = null;
        if (!CollectionUtils.isEmpty(homeMenuList)) {
            Set<String> seenIds = new HashSet<>();
            menus = homeMenuList.stream().filter(f -> seenIds.add(f.getMenuCode())).collect(Collectors.toList());
        }
        return menus;
    }

    @Override
    public List<HomeMenuEntity> queryMenusByRoleId(Long roleId) {
        List<HomeMenu> homeMenus = homeMenuDao.queryMenusByRoleId(roleId);
        return homeMenus.stream().map(item -> {
            HomeMenuEntity homeMenuEntity = new HomeMenuEntity();
            homeMenuEntity.setMenuName(item.getMenuName());
            homeMenuEntity.setMenuCode(item.getMenuCode());
            homeMenuEntity.setIcon(item.getIcon());
            homeMenuEntity.setOrder(item.getOrder());
            return homeMenuEntity;
        }).collect(Collectors.toList());
    }

    @Override
    public String saveUserToken(String username, Map<String, Object> Claims) {
        // 使用jwt生成token
        String token = JwtUtils.generateToken(username, Claims);
        redisService.setValue(RedisConstants.LOGIN_TOKEN + username, token, 7200000L);
        return token;
    }

    @Override
    public boolean checkToken(String username, String tokenHeader) {
        boolean exists = redisService.isExists(RedisConstants.LOGIN_TOKEN + username);
        if (exists) {
            String value = redisService.getValue(RedisConstants.LOGIN_TOKEN + username);
            if (value.equals(tokenHeader)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean checkCode(String key, String code) {
        boolean exists = redisService.isExists(key);
        if (exists) {
            String value = redisService.getValue(key);
            if (value.equals(code)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void saveLoginLog(LoginLogEntity loginLogEntity) {
        HomeLoginLog homeLoginLog = HomeLoginLog.builder()
                .username(loginLogEntity.getUsername())
                .ip(loginLogEntity.getIp())
                .os(loginLogEntity.getOs())
                .loginType(loginLogEntity.getLoginType())
                .deviceType(loginLogEntity.getDeviceType())
                .browserVersion(loginLogEntity.getBrowserVersion())
                .browser(loginLogEntity.getBrowser())
                .loginTime(loginLogEntity.getLoginTime())
                .build();
        homeLoginLogDao.insert(homeLoginLog);
    }

    @Override
    public UserInfoAggregate queryByUserId(Long userId) {
        HomeUserEntity homeUserEntity = HomeUserEntity.builder().build();
        HomeUser homeUser = homeUserDao.queryUserById(userId);
        BeanUtils.copyProperties(homeUser, homeUserEntity);

        HomeUserDetailEntity homeUserDetailEntity = HomeUserDetailEntity.builder().build();
        HomeUserDetail homeUserDetail = homeUserDetailDao.queryByUserId(userId);
        BeanUtils.copyProperties(homeUserDetail, homeUserDetailEntity);
        return UserInfoAggregate.builder()
                .homeUserEntity(homeUserEntity)
                .homeUserDetailEntity(homeUserDetailEntity)
                .build();
    }

    @Override
    public void saveUserDetail(HomeUserDetailEntity homeUserDetailEntity) {
        HomeUserDetail homeUserDetail = HomeUserDetail.builder().build();
        BeanUtils.copyProperties(homeUserDetailEntity, homeUserDetail);
        homeUserDetailDao.insert(homeUserDetail);
    }

    @Override
    public void editUserDetail(HomeUserDetailEntity homeUserDetailEntity) {
        HomeUserDetail homeUserDetail = HomeUserDetail.builder().build();
        BeanUtils.copyProperties(homeUserDetailEntity, homeUserDetail);
        homeUserDetailDao.updateBuUserId(homeUserDetail);
    }
}
